package com.alibaba.citrus.cr.sales.plan.facade.service.setting;

import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.sales.plan.api.setting.LoginService;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.ChangePasswordRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.ResetPasswordEmailRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.ResetPasswordPhoneRequest;
import com.alibaba.citrus.cr.sales.plan.model.enums.ResetPasswordVerificationModeEnum;
import com.alibaba.citrus.cr.sales.plan.repository.SendHistoryRecordRepository;
import com.alibaba.citrus.cr.sales.plan.sdo.NotificationConfigSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SendHistoryRecordSDO;
import com.alibaba.citrus.cr.sales.plan.sdo.SendMailSDO;
import com.alibaba.cz.base.tool.DateUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice.exception.ErrorMessage;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.model.dto.BaselineGetEmployeesEs2Request;
import com.epoch.app.bcorder.model.dto.EmployeeResetPasswordsRequest;
import com.epoch.app.bcorder.model.dto.EmployeeSDO;
import com.epoch.app.bcorder.model.enums.NoticeTitle;
import com.epoch.app.bcorder.model.enums.YztMessageResultEnum;
import com.epoch.app.bcorder.sales_plan.notificationconfig.dto.BoNotificationConfigGetList2Request;
import com.epoch.app.bcorder.sales_plan.notificationconfig.dto.BoNotificationConfigGetList2Response;
import com.epoch.app.bcorder.sales_plan.notificationconfig.service.NotificationConfigService;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.BcOrderService;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;

import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author zhoubc
 * @description: TODO
 * @date 2023/2/8 16:39
 */
@Service
public class LoginServiceImpl implements LoginService {
    private static final Log log = Log.getLogger(LoginService.class);

    @Resource
    private BcOrderService bcOrderService;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private EpochCacheService epochCacheService;

    @Resource
    private NotificationConfigService notificationConfigService;

    @Resource
    private SendHistoryRecordRepository sendHistoryRecordRepository;

    @Override
    @FacadeInvoker
    public Result<SendMailSDO> resetPasswordEmail(ResetPasswordEmailRequest resetPasswordEmailRequest) {
        //用户传入  对应的邮箱
        if (resetPasswordEmailRequest == null || StringUtils.isBlank(resetPasswordEmailRequest.getEmail())) {
            throw new FacadeException("OTS-01-001-01-15-005");
        }

        checkRepeatSubmit(resetPasswordEmailRequest.getEmail());
        checkResetPasswordNumber(resetPasswordEmailRequest.getEmail());

        BaselineGetEmployeesEs2Request getEmployeesRequest = new BaselineGetEmployeesEs2Request();
        getEmployeesRequest.setEmail(resetPasswordEmailRequest.getEmail());
        Result<List<EmployeeSDO>> employeeResult = baseDataService.baselineGetEmployeesEs2(getEmployeesRequest);
        if (Objects.isNull(employeeResult) || CollectionUtils.isEmpty(employeeResult.getResult())) {
            throw new FacadeException("OTS-01-001-01-15-006");
        }

        BoNotificationConfigGetList2Request configGetListRequest = new BoNotificationConfigGetList2Request();
        configGetListRequest.setTitle(NoticeTitle.Password_Reset.getValue().toString());
        configGetListRequest.setSendMethod(ResetPasswordVerificationModeEnum.EMAIL.getType());
        BoNotificationConfigGetList2Response listResponse = notificationConfigService.boNotificationConfigGetList2(configGetListRequest);
        if (Objects.isNull(listResponse) || CollectionUtils.isEmpty(listResponse.getResult())) {
            throw new FacadeException("OTS-01-001-01-15-003");
        }
        List<NotificationConfigSDO> notificationConfigList = JSONArray.parseArray(JSONObject.toJSONString(listResponse.getResult()),NotificationConfigSDO.class);
        NotificationConfigSDO notificationTemplete = notificationConfigList.get(0);
        //如果该模板的状态为禁用状态 提示该模板以禁用 如需使用请启用
        if (notificationTemplete.getStatus().equals(0)) {
            throw new FacadeException("OTS-01-001-01-15-022");
        }
        if (StringUtils.isBlank(notificationTemplete.getContent())) {
            throw new FacadeException("OTS-01-001-01-15-026");
        }

        //将发送模板数据进行封装 返回
        SendMailSDO resetPasswordEmailSDO = new SendMailSDO();
        resetPasswordEmailSDO.setTitle(notificationTemplete.getLabel());
        resetPasswordEmailSDO.setRecipient(resetPasswordEmailRequest.getEmail());
        String content = formatContent(notificationTemplete.getContent(),"Verification_Code_Email"+resetPasswordEmailRequest.getEmail());
        resetPasswordEmailSDO.setContent(content);

        //发送后 进行保存发送记录
        SendHistoryRecordSDO sendHistoryRecordSDO = new SendHistoryRecordSDO();
        sendHistoryRecordSDO.setNotificationId(String.valueOf(notificationTemplete.getId()));
        sendHistoryRecordSDO.setLabel(notificationTemplete.getLabel());
        sendHistoryRecordSDO.setTitle(notificationTemplete.getTitle());
        sendHistoryRecordSDO.setSendMethod(ResetPasswordVerificationModeEnum.EMAIL.getType());
        sendHistoryRecordSDO.setSendTime(new Date());
        sendHistoryRecordSDO.setRecipient(resetPasswordEmailRequest.getEmail());
        sendHistoryRecordSDO.setStatus(1);
        Map<String,String> features = new HashMap<>();
        features.put("content",content);
        sendHistoryRecordSDO.setFeatures(JSONObject.toJSONString(features));
        sendHistoryRecordRepository.save(sendHistoryRecordSDO);

        saveSubmitRequestCache(resetPasswordEmailRequest.getEmail());
        saveResetPasswordNumberCache(resetPasswordEmailRequest.getEmail());

        return Result.success(resetPasswordEmailSDO);
    }

    @Override
    @FacadeInvoker
    public Result<SendMailSDO> resetPasswordSendPhone(ResetPasswordPhoneRequest resetPasswordPhoneRequest) {
        //用户传入  对应的手机号
        if (resetPasswordPhoneRequest == null || StringUtils.isBlank(resetPasswordPhoneRequest.getPhone())) {
            throw new FacadeException("OTS-01-001-01-15-005");
        }

        checkRepeatSubmit(resetPasswordPhoneRequest.getPhone());
        checkResetPasswordNumber(resetPasswordPhoneRequest.getPhone());

        BaselineGetEmployeesEs2Request getEmployeesRequest = new BaselineGetEmployeesEs2Request();
        getEmployeesRequest.setPhone(resetPasswordPhoneRequest.getPhone());
        Result<List<EmployeeSDO>> employeeResult = baseDataService.baselineGetEmployeesEs2(getEmployeesRequest);
        if (Objects.isNull(employeeResult) || CollectionUtils.isEmpty(employeeResult.getResult())) {
            throw new FacadeException("OTS-01-001-01-15-006");
        }

        BoNotificationConfigGetList2Request configGetListRequest = new BoNotificationConfigGetList2Request();
        configGetListRequest.setTitle(NoticeTitle.Password_Reset.getValue().toString());
        configGetListRequest.setSendMethod(ResetPasswordVerificationModeEnum.PHONE.getType());
        BoNotificationConfigGetList2Response listResponse = notificationConfigService.boNotificationConfigGetList2(configGetListRequest);
        if (Objects.isNull(listResponse) || CollectionUtils.isEmpty(listResponse.getResult())) {
            throw new FacadeException("OTS-01-001-01-15-003");
        }

        List<NotificationConfigSDO> notificationConfigList = JSONArray.parseArray(JSONObject.toJSONString(listResponse.getResult()),NotificationConfigSDO.class);
        NotificationConfigSDO notificationTemplete = notificationConfigList.get(0);
        //如果该模板的状态为禁用状态 提示该模板以禁用 如需使用请启用
        if (notificationTemplete.getStatus().equals(0)) {
            throw new FacadeException("OTS-01-001-01-15-022");
        }
        if (StringUtils.isBlank(notificationTemplete.getContent())) {
            throw new FacadeException("OTS-01-001-01-15-026");
        }

        //将发送模板数据进行封装 返回
        SendMailSDO resetPasswordPhoneSDO = new SendMailSDO();
        resetPasswordPhoneSDO.setRecipient(resetPasswordPhoneRequest.getPhone());
        String content = formatContent(notificationTemplete.getContent(),"Verification_Code_Phone"+resetPasswordPhoneRequest.getPhone());
        if (content.length()>500) {
            throw new FacadeException("OTS-01-001-01-15-028");
        }
        resetPasswordPhoneSDO.setContent(content);
        resetPasswordPhoneSDO.setNotificationId(String.valueOf(notificationTemplete.getId()));

        saveSubmitRequestCache(resetPasswordPhoneRequest.getPhone());
        saveResetPasswordNumberCache(resetPasswordPhoneRequest.getPhone());

        return Result.success(resetPasswordPhoneSDO);
    }

    private String formatContent(String content, String keyValue){
        //随机生成6位验证码
        String verificationCode = (int) ((Math.random() * 9 + 1) * 100000) + "";
        //将验证码存储到redis  有效期30分钟
        String verificationKey = keyValue;
        epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(), verificationKey, verificationCode, 30L, TimeUnit.MINUTES);
        String contents = MessageFormat.format(content, verificationCode);
        return contents;
    }

    private void saveSubmitRequestCache(String code){
        String uuid = UUID.randomUUID().toString();
        epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(), "reset_password_send_submit_"+code, uuid, 60L, TimeUnit.SECONDS);
    }

    private void checkRepeatSubmit(String code){
        if(StringUtils.isNotBlank(epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(),"reset_password_send_submit_"+code))){
            throw new FacadeException("OTS-01-001-01-15-027");
        }
    }

    private void saveResetPasswordNumberCache(String code){
        String date = DateUtils.toDateStr(new Date(), DateUtils.DATE_FORMAT);
        String cachekey = "reset_password_send_submit_number_"+date+"_"+code;
        String count = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(),cachekey);
        if(StringUtils.isBlank(count)){
            count = "1";
        }else{
            count = String.valueOf(Integer.valueOf(count)+1);
        }
        epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(), cachekey, count, 1L, TimeUnit.DAYS);
    }

    private void checkResetPasswordNumber(String code){
        String date = DateUtils.toDateStr(new Date(), DateUtils.DATE_FORMAT);
        String count = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(),"reset_password_send_submit_number_"+date+"_"+code);
        if(StringUtils.isBlank(count)){
            count = "1";
        }else{
            count = String.valueOf(Integer.valueOf(count)+1);
        }

        Long limitNumber = BcOrderConstants.RESET_PASSWORD_SEND_NUMBER()==null?20L:BcOrderConstants.RESET_PASSWORD_SEND_NUMBER();
        if(Integer.valueOf(count)>limitNumber){
            throw new FacadeException("OTS-01-001-01-15-029");
        }
    }

    @Override
    @FacadeInvoker
    public Result<String> sendMessageCallback(String notificationId, String recipient, String content, String restResult){
        YztMessageResultEnum restResultEnum = YztMessageResultEnum.of(restResult);

        //发送后 进行保存发送记录
        SendHistoryRecordSDO sendHistoryRecordSDO = new SendHistoryRecordSDO();
        sendHistoryRecordSDO.setNotificationId(notificationId);
        sendHistoryRecordSDO.setRecipient(recipient);
        sendHistoryRecordSDO.setTitle(NoticeTitle.Password_Reset.getValue().toString());
        sendHistoryRecordSDO.setLabel(NoticeTitle.Password_Reset.getLabel());
        sendHistoryRecordSDO.setSendMethod(ResetPasswordVerificationModeEnum.PHONE.getType());
        sendHistoryRecordSDO.setSendTime(new Date());

        Map<String,String> features = new HashMap<>();
        features.put("content",content);
        if(NumberUtils.isNumber(restResult) && Long.valueOf(restResult)>0){
            sendHistoryRecordSDO.setStatus(1);
            features.put("submitResult", restResult+"_"+YztMessageResultEnum.SUCCESS.getLabel());
        }else{
            if(restResultEnum == null){
                throw new FacadeException("OTS-02-007-00-16-999");
            }
            sendHistoryRecordSDO.setStatus(2);
            features.put("submitResult", restResult+"_"+restResultEnum.getLabel());
        }
        sendHistoryRecordSDO.setFeatures(JSONObject.toJSONString(features));
        String id = sendHistoryRecordRepository.save(sendHistoryRecordSDO);

        if(NumberUtils.isNumber(restResult) && Long.valueOf(restResult)>0){
            return Result.success(content);
        }else{
            return Result.fail(restResultEnum.getValue()+"_"+restResultEnum.getLabel(),restResultEnum.getTips());
        }
    }

    /**
     * 修改密码
     *
     * @param changePasswordRequest
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> changePassword(ChangePasswordRequest changePasswordRequest) {
        EmployeeSDO employee = null;
        String verificationKey = null;
        if (StringUtils.isBlank(changePasswordRequest.getMode())) {
            throw new FacadeException("OTS-01-001-01-15-024");
        }else{
            BaselineGetEmployeesEs2Request getEmployeesRequest = new BaselineGetEmployeesEs2Request();
            Result<List<EmployeeSDO>> employeeResult = null;
            //验证方式  1邮箱 2手机号 获取当前要修改的员工
            if(changePasswordRequest.getMode().equals(ResetPasswordVerificationModeEnum.EMAIL.getType().toString())){
                if (StringUtils.isBlank(changePasswordRequest.getEmail())) {
                    throw new FacadeException("OTS-01-001-01-15-005");
                }
                getEmployeesRequest.setEmail(changePasswordRequest.getEmail());
                employeeResult = baseDataService.baselineGetEmployeesEs2(getEmployeesRequest);
                verificationKey = "Verification_Code_Email" + changePasswordRequest.getEmail();
            }else if(changePasswordRequest.getMode().equals(ResetPasswordVerificationModeEnum.PHONE.getType().toString())){
                if (StringUtils.isBlank(changePasswordRequest.getPhone())) {
                    throw new FacadeException("OTS-01-001-01-15-025");
                }
                getEmployeesRequest.setPhone(changePasswordRequest.getPhone());
                employeeResult = baseDataService.baselineGetEmployeesEs2(getEmployeesRequest);
                verificationKey = "Verification_Code_Phone" + changePasswordRequest.getPhone();
            }else{
                throw new FacadeException("OTS-01-001-01-15-024");
            }

            if (Objects.isNull(employeeResult) || CollectionUtils.isEmpty(employeeResult.getResult())) {
                throw new FacadeException("OTS-01-001-01-15-030");
            }
            employee = employeeResult.getResult().get(0);
        }

        //判断验证码错误次数
        Long limitNumber = checkVerificationErrorCount(employee.getId());

        if (StringUtils.isBlank(changePasswordRequest.getVerificationCode())) {
            throw new FacadeException("OTS-01-001-01-15-008");
        }
        if (StringUtils.isBlank(changePasswordRequest.getFirstPassword())) {
            throw new FacadeException("OTS-01-001-01-15-009");
        }
        if (StringUtils.isBlank(changePasswordRequest.getSecondPassword())) {
            throw new FacadeException("OTS-01-001-01-15-010");
        }

        //获取发送的验证码
        String verificationCode = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(), verificationKey);
        if (StringUtils.isBlank(verificationCode)) {
            throw new FacadeException("OTS-01-001-01-15-011");
        }

        //判断验证码是否一致
        if (!changePasswordRequest.getVerificationCode().equals(verificationCode)) {
            long remainNum = saveCheckVerificationErrorCount(employee.getId());
            if (remainNum == 0) {
                throw new FacadeException("OTS-01-001-01-15-032",limitNumber);
            } else {
                throw new FacadeException("OTS-01-001-01-15-031",remainNum);
            }
        }
        //判断第一次输入的密码和二次确认密码是否一致
        if (!changePasswordRequest.getFirstPassword().equals(changePasswordRequest.getSecondPassword())) {
            throw new FacadeException("OTS-01-001-01-15-012");
        }

        //如果密码一致  并且 验证码正确 那么让其修改密码  保存
        EmployeeResetPasswordsRequest resetPasswordsRequest = new EmployeeResetPasswordsRequest();
        resetPasswordsRequest.setEmployeeId(employee.getId());
        resetPasswordsRequest.setPassword(changePasswordRequest.getFirstPassword());
        resetPasswordsRequest.setApiContext(employee);

        Result<Boolean> updateResult = bcOrderService.employeeResetPasswords(resetPasswordsRequest);
        if(updateResult==null || !updateResult.isSuccess()){
            throw new FacadeException("OTS-01-001-01-15-014",updateResult!=null?updateResult.getMessage():"接口调用异常");
        }
        //修改成功，验证码用完之后需要进行删除
        epochCacheService.remove(BcOrderConstants.REDIS_CACHE_CODE(), Lists.newArrayList(verificationKey));
        return Result.success(true);
    }

    @Override
    public Result<Boolean> removeVerificationLimitCache(String employeeId) {
        String cachekey = "reset_password_check_verification_"+employeeId;
        epochCacheService.remove(BcOrderConstants.REDIS_CACHE_CODE(), Lists.newArrayList(cachekey));
        return Result.success(true);
    }

    private long saveCheckVerificationErrorCount(String code){
        String cachekey = "reset_password_check_verification_"+code;
        String count = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(),cachekey);
        if(StringUtils.isBlank(count)){
            count = "1";
        }else{
            count = String.valueOf(Integer.valueOf(count)+1);
        }

        epochCacheService.put(BcOrderConstants.REDIS_CACHE_CODE(), cachekey, count, 1L, TimeUnit.DAYS);
        Long limitNumber = BcOrderConstants.RESET_PASSWORD_CHECK_VERIFICATION_LIMIT()==null?3L:BcOrderConstants.RESET_PASSWORD_CHECK_VERIFICATION_LIMIT();
        Long remainNum = limitNumber-Long.valueOf(count);
        return remainNum;
    }

    private Long checkVerificationErrorCount(String code){
        String count = epochCacheService.get(BcOrderConstants.REDIS_CACHE_CODE(),"reset_password_check_verification_"+code);
        if(StringUtils.isBlank(count)){
            count = "1";
        }else{
            count = String.valueOf(Integer.valueOf(count)+1);
        }

        Long limitNumber = BcOrderConstants.RESET_PASSWORD_CHECK_VERIFICATION_LIMIT()==null?3L:BcOrderConstants.RESET_PASSWORD_CHECK_VERIFICATION_LIMIT();
        if(Integer.valueOf(count)>limitNumber){
            throw new FacadeException("OTS-01-001-01-15-032",limitNumber);
        }
        return limitNumber;
    }



}
